// 远程桌面共享相关头文件
#include "remote_common.h"
#include "opencv_version.h"
#include "log_manager.h"

// 第三方库头文件
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XTest.h>
#include <jpeglib.h>

// 操作系统相关头文件
#include <sys/time.h>
#include <setjmp.h>

// C++11标准头文件
#include <iostream>
#include <fstream> 
#include <istream> 
#include <ostream>
#include <vector>
#include <string>
#include <cstdio>
#include <ctime>
#include <chrono>
#include <thread>
#include <cmath>
#include <mutex>


#define CONFIG_SEND_FRAME_RAWDATA  // 发送原始帧（1920x1200x3 == 6.9MB）


// 日志模块
static LogManager logger("server.log", 20 * 1024 * 1024);



// 1. 共享的 X11 Display 句柄（进程初始化时创建，全程不销毁，除非程序退出）
static Display* g_display = nullptr;
// 2. 保护 Display* 访问的互斥锁
static std::mutex g_display_mutex;

// 初始化 X11 连接（主进程/初始化线程调用）
bool X11_init() {
    g_display = XOpenDisplay(nullptr); // nullptr 表示使用默认 DISPLAY 环境变量（如 :0）
    if (g_display == nullptr) {
        std::cerr << "Failed to open X11 display!" << std::endl;
        return false;
    }
    return true;
}

// 释放 X11 连接（程序退出前调用，仅调用一次）
void X11_exit() {
    if (g_display != nullptr) {
        XCloseDisplay(g_display);
        g_display = nullptr;
    }
}

// 通过下面接口统一安全访问 g_display 实例

KeyCode X11_keysym_to_x11key(KeySym ks) { 
    std::lock_guard<std::mutex> lock(g_display_mutex);
    return XKeysymToKeycode(g_display, ks);
}

KeySym X11_x11key_to_keysym(KeyCode kc) { 
    std::lock_guard<std::mutex> lock(g_display_mutex);
    return XKeycodeToKeysym(g_display, kc, 0);
}

void X11_GetKeyMap(char keymap[])
{
    std::lock_guard<std::mutex> lock(g_display_mutex);
    XQueryKeymap(g_display, keymap);
}

void X11_GetScreenInfo(Window &root, int& screen_width, int& screen_height)
{
    std::lock_guard<std::mutex> lock(g_display_mutex);
    int screen_num = DefaultScreen(g_display);
    root = RootWindow(g_display, screen_num);
    screen_width = DisplayWidth(g_display, screen_num);
    screen_height = DisplayHeight(g_display, screen_num);
}

void X11_FakeMouseMotionEvent(int &x, int &y)
{
    std::lock_guard<std::mutex> lock(g_display_mutex);
    XTestFakeMotionEvent(g_display, 0, x, y, 0);
    XFlush(g_display);
}

void X11_FakeButtonEvent(int button, int is_press)
{
    std::lock_guard<std::mutex> lock(g_display_mutex);
    XTestFakeButtonEvent(g_display, button, is_press, 0);
    XFlush(g_display);
}

void X11_FakeKeyEvent(int button, int is_press)
{
    std::lock_guard<std::mutex> lock(g_display_mutex);
    XTestFakeKeyEvent(g_display, button, is_press, 0);
    XFlush(g_display);
}


// 错误处理结构体
struct jpeg_error_mgr_custom {
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};

// JPEG错误处理回调
METHODDEF(void) jpeg_error_exit(j_common_ptr cinfo) {
    struct jpeg_error_mgr_custom* myerr = (struct jpeg_error_mgr_custom*)cinfo->err;
    (*cinfo->err->output_message)(cinfo);
    longjmp(myerr->setjmp_buffer, 1);
}

/**
 * 将RGB格式的屏幕数据保存为JPG图片（不依赖OpenCV，使用libjpeg）
 * @param screen_data 原始RGB屏幕数据（每个像素3字节，顺序为R、G、B）
 * @param width 图像宽度
 * @param height 图像高度
 * @param filename 保存的文件名（需包含.jpg扩展名）
 * @param quality JPG质量（1-100，数值越高质量越好）
 * @return 保存成功返回true，失败返回false
 */
bool save_screen_to_jpg(const std::vector<unsigned char>& screen_data,
                       int width, int height,
                       const std::string& filename,
                       int quality = 100) {
    // 检查输入参数有效性
    if (screen_data.empty() || width <= 0 || height <= 0 || 
        screen_data.size() != static_cast<size_t>(width * height * 3)) {
        fprintf(stderr, "无效的输入参数：数据大小与分辨率不匹配\n");
        return false;
    }

    // 限制质量范围
    quality = (quality < 1) ? 1 : (quality > 100) ? 100 : quality;

    // 打开输出文件
    FILE* outfile = fopen(filename.c_str(), "wb");
    if (!outfile) {
        perror("无法打开输出文件");
        return false;
    }

    // 初始化JPEG压缩对象
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr_custom jerr;

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = jpeg_error_exit;

    // 设置错误处理的跳转点
    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_compress(&cinfo);
        fclose(outfile);
        return false;
    }

    // 初始化压缩对象
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

    // 设置图像参数
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;               // RGB三个通道
    cinfo.in_color_space = JCS_RGB;           // 输入格式为RGB

    // 设置默认参数
    jpeg_set_defaults(&cinfo);
    // 设置压缩质量
    jpeg_set_quality(&cinfo, quality, TRUE);

    // 开始压缩
    jpeg_start_compress(&cinfo, TRUE);

    // 处理每行像素（注意：libjpeg需要从上到下扫描，且每行数据需对齐）
    JSAMPROW row_pointer[1];
    int row_stride = width * 3;  // 每行的字节数

    // 由于屏幕数据是从顶部到底部存储的，直接按行处理即可
    for (int y = 0; y < height; y++) {
        // 获取当前行的起始地址
        const unsigned char* row_data = &screen_data[y * row_stride];
        row_pointer[0] = const_cast<JSAMPLE*>(reinterpret_cast<const JSAMPLE*>(row_data));
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    // 完成压缩并清理资源
    jpeg_finish_compress(&cinfo);
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);

    printf("成功保存JPG图片：%s（分辨率：%dx%d）\n", filename.c_str(), width, height);
    return true;
}


/**
 * @brief 生成RGB格式的屏幕数据，用来作为测试数据
 *
 * @param rgb_index 0=R, 1=G, 2=B
 * @param width
 * @param height
 * @return std::vector<unsigned char>
 */
std::vector<unsigned char> generate_rgb_screen_data(int rgb_index, int width, int height)
{
    // 服务端替换 capture_screen 调用，发送纯色图像
    std::vector<unsigned char> screen_data(width * height * PIXEL_BYTES, 0);
    // 填充为红色（R=255, G=0, B=0）
    if (rgb_index == 0) {
        for (int i = 0; i < screen_data.size(); i += 3) {
            screen_data[i] = 255;   // R
            screen_data[i+1] = 0;   // G
            screen_data[i+2] = 0;   // B
        }
    } else if (rgb_index == 1) {
        for (int i = 0; i < screen_data.size(); i += 3) {
            screen_data[i] = 0;     // R
            screen_data[i+1] = 255; // G
            screen_data[i+2] = 0;     // B
        }
    } else {
        for (int i = 0; i < screen_data.size(); i += 3) {
            screen_data[i] = 0;     // R
            screen_data[i+1] = 0;   // G
            screen_data[i+2] = 255; // B
        }
    }
    return screen_data;
}


/**
 * @brief 捕获屏幕图像
 * 将捕获的原始屏幕图像缩放到较低分辨率后再传输。这样既能减少数据传输量，也能提高远程控制的流畅度。
 * @param root 
 * @param width   要缩放的目标分辨率
 * @param height  要缩放的目标分辨率
 * @return std::vector<unsigned char> 
 */
std::vector<unsigned char> capture_screen(Window root, int width, int height) {
    std::vector<unsigned char> buffer(width * height * PIXEL_BYTES);
    XImage* image;
    {
        std::lock_guard<std::mutex> lock(g_display_mutex);
        image = XGetImage(g_display, root, 0, 0, width, height, AllPlanes, ZPixmap);
        if (!image) {
            logger.log_warn("屏幕捕获失败");
            return buffer;
        }
    }

    
    // 转换为RGB格式
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint32_t pixel = XGetPixel(image, x, y);
            
            // 从XImage的像素格式中提取RGB值
            unsigned char blue = (pixel >> 0) & 0xFF;
            unsigned char green = (pixel >> 8) & 0xFF;
            unsigned char red = (pixel >> 16) & 0xFF;
            
            // 存储为RGB格式
            size_t index = (y * width + x) * PIXEL_BYTES;
            buffer[index] = red;
            buffer[index + 1] = green;
            buffer[index + 2] = blue;
        }
    }
    
    XDestroyImage(image);
    return buffer;
}




#ifdef CONFIG_SEND_FRAME_RAWDATA
bool send_frame_rawdata(Window &root, int width, int height, int sockfd_screen)
{
    // 1. 捕获并发送屏幕数据
    std::vector<unsigned char> screen_data = capture_screen(root, width, height);
    if (screen_data.size() > 0)
    {
        // logger.log_debug("捕获到一帧图像");

        // 发送屏幕数据
        PacketHeader header;
        header.type = SCREEN_DATA;
        header.data_size = screen_data.size();
        
        if (!send_all(sockfd_screen, &header, sizeof(header)) || 
            !send_all(sockfd_screen, screen_data.data(), screen_data.size())) {
            logger.log_warn("发送屏幕数据失败，客户端已断开连接");
            return false;
        }

        // logger.log_debug("已发送一帧图像");
        return true;
    }
    return false;
}
#endif // CONFIG_SEND_FRAME_RAWDATA




// 服务端鼠标状态跟踪
struct ServerMouseState {
    bool left_button_pressed = false;  // 记录左键是否处于按下状态
} server_mouse_state;

/**
 * @brief 模拟鼠标事件（增强拖拽处理）
 * 
 * @param display 
 * @param event 
 * @param original_width 
 * @param original_height 
 * @param scaled_width   缩放后的宽度
 * @param scaled_height  缩放后的高度
 */
void simulate_mouse_event(const MouseEvent& event, 
                         int original_width, int original_height, int scaled_width, int scaled_height) {
    // 计算原始屏幕坐标（将缩放后的坐标映射回去）
    int original_x = static_cast<int>(event.x * (original_width / static_cast<double>(scaled_width)));
    int original_y = static_cast<int>(event.y * (original_height / static_cast<double>(scaled_height)));
    
    // 限制坐标在屏幕范围内
    original_x = std::max(0, std::min(original_x, original_width - 1));
    original_y = std::max(0, std::min(original_y, original_height - 1));
    
    // 移动鼠标（拖拽时持续发送移动事件）
    X11_FakeMouseMotionEvent(original_x, original_y);

    
    // 处理滚轮事件（使用X11的鼠标按钮4和5模拟滚轮）
    if (event.wheel_delta == 1 || event.wheel_delta == -1) {

        // 在windows里，直接调用 mouse_event 函数
        // mouse_event(MOUSEEVENTF_WHEEL, 0, 0, event.wheel_delta * 120, 0);


        // 配置滚动参数（可根据需要调整）
        const int SCROLL_STEPS = 3;         // 每次滚轮事件的滚动步数
        const int SCROLL_DELAY_MS = 10;     // 步间延迟（毫秒）
        const unsigned int SCROLL_IN_BUTTON = 5;   // 向手心滚动（下滚）
        const unsigned int SCROLL_OUT_BUTTON = 4;  // 向外滚动（上滚）
        
        // 确定滚动方向和按钮
        unsigned int scroll_button = (event.wheel_delta == 1) ? SCROLL_IN_BUTTON : SCROLL_OUT_BUTTON;
        
        logger.log_debug("远端鼠标滚轮请求事件: 方向=%s, 位置=(%d,%d)",
                       (event.wheel_delta == 1 ? "向手心" : "向外"),
                       original_x, original_y);
        
        // 多步滚动模拟，增强滚动手感
        for (int i = 0; i < SCROLL_STEPS; ++i) {
            // 模拟滚轮按下
            X11_FakeButtonEvent(scroll_button, True);
            // X11_Flush();
            
            // 短暂延迟，确保系统能识别滚动动作
            usleep(SCROLL_DELAY_MS * 1000);
            
            // 模拟滚轮释放
            X11_FakeButtonEvent(scroll_button, False);
            // X11_Flush();
            
            // 步间延迟，控制滚动速度
            if (i < SCROLL_STEPS - 1) {
                usleep(SCROLL_DELAY_MS * 1000);
            }
        }

    }


    // 处理左键按下
    else if (event.left_down && !server_mouse_state.left_button_pressed) {
        // XTestFakeButtonEvent(display, 1, True, 0);  // 按下左键
        X11_FakeButtonEvent(1, True);
        server_mouse_state.left_button_pressed = true;
    }
    // 处理左键释放
    else if (!event.left_down && server_mouse_state.left_button_pressed) {
        // XTestFakeButtonEvent(display, 1, False, 0); // 释放左键
        X11_FakeButtonEvent(1, False);
        server_mouse_state.left_button_pressed = false;
    }
    // 拖拽状态特殊处理（确保按键保持按下）
    else if (event.dragging && server_mouse_state.left_button_pressed) {
        // 持续按住左键并移动，不需要额外操作，因为上面已经发送了移动事件
        // 这里可以添加拖拽优化逻辑，如降低高频事件的处理频率
    }
    // 处理右键事件
    else if (event.right_down) {
        // XTestFakeButtonEvent(display, 3, True, 0);  // 按下右键
        // XTestFakeButtonEvent(display, 3, False, 0); // 立即释放右键（简单处理）
        X11_FakeButtonEvent(3, True);
        X11_FakeButtonEvent(3, False);
    }

    // XFlush(display);
    // X11_Flush();
}

#if 0
// 模拟鼠标事件
void simulate_mouse_event(Display* display, const MouseEvent& event) {
    // 移动鼠标
    XTestFakeMotionEvent(display, 0, event.x, event.y, CurrentTime);
    
    // 处理左键
    XTestFakeButtonEvent(display, 1, event.left_down, CurrentTime);
    
    // 处理右键
    XTestFakeButtonEvent(display, 3, event.right_down, CurrentTime);




    // 处理双击(0.5秒内双击)
    static MouseEvent last_event;
    static timeval last_time;
    if (event.left_down && last_event.left_down) {
        timeval current_time;
        gettimeofday(&current_time, nullptr);
        long elapsed = (current_time.tv_sec - last_time.tv_sec) * 1000 +
                       (current_time.tv_usec - last_time.tv_usec) / 1000;
        if (elapsed < 500) {
            // 触发双击事件
            XTestFakeButtonEvent(display, 1, True, CurrentTime);
            XTestFakeButtonEvent(display, 1, False, CurrentTime);
        }
    }
    last_event = event;
    gettimeofday(&last_time, nullptr);





    // 处理鼠标左键长按
    if (event.left_down) {
        XTestFakeButtonEvent(display, 1, True, CurrentTime);
    } else {
        XTestFakeButtonEvent(display, 1, False, CurrentTime);
    }

    XFlush(display);
}
#endif //if 0

// 模拟键盘事件
void simulate_keyboard_event(const KeyboardEvent& event) {
    std::lock_guard<std::mutex> lock(g_display_mutex);
    XTestFakeKeyEvent(g_display, event.keycode, event.pressed, CurrentTime);
    XFlush(g_display);
}


bool recv_config_data(int client_socket, ConfigData& config_data)
{
    PacketHeader event_header;
    if (!recv_all(client_socket, &event_header, sizeof(event_header))) {
        logger.log_error("接收事件头部失败，客户端已断开连接");
        return false;
    }

    if (event_header.type == CONFIG_DATA && event_header.data_size == sizeof(ConfigData)) {
        if (recv_all(client_socket, &config_data, sizeof(config_data))) {
            return true;
        }
    } else
    {
        logger.log_warn("获取配置数据失败,主控端必须优先发送配置数据");
        return false;
    }
    return false;
}

// 创建服务端套接字，然后绑定端口，然后返回服务端套接字
bool create_server_socket(int &server_socket, uint16_t server_port)
{
    // 创建服务器套接字
    server_socket = create_tcp_socket();
    if (server_socket < 0) {
        return false;
    }
    
    // 设置地址复用
    int opt = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    // 绑定并监听
    sockaddr_in server_addr;
    std::memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(server_port);
    
    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        logger.log_error("绑定失败,%s", strerror(errno));
        close(server_socket);
        return false;
    }
    
    if (listen(server_socket, 1) < 0) {
        logger.log_error("监听失败,%s", strerror(errno));
        close(server_socket);
        return false;
    }
    return true;
}

void thread_send_screen(int scaled_width, int scaled_height)
{
    // 创建控制服务套接字
    int server_socket_control = 0;
    logger.log_info("被控端已启动, 监听屏幕端口: %d ...", PORT_SCREEN);
    if (!create_server_socket(server_socket_control, PORT_SCREEN))
    {
        logger.log_error("创建服务端套接字失败");
        return ;
    }
    logger.log_info("被控端已启动, 监听屏幕端口: %d 完成", PORT_SCREEN);


    // 紧接着等待客户端连接
    logger.log_info("等待客户端已连接屏幕: ...");
    // 接受客户端连接
    sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    int client_socket_control = 0;
    client_socket_control = accept(server_socket_control, (struct sockaddr*)&client_addr, &client_len);
    
    if (client_socket_control < 0) {
        logger.log_error("接受连接失败,%s", strerror(errno));
        close(server_socket_control);
        return ;
    }
    
    char client_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
    logger.log_info("等待客户端已连接屏幕: %s:%d 完成", client_ip, ntohs(client_addr.sin_port));


    // 从队列里拿到帧数据并发送给客户端
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }


    logger.log_info("客户端已连接屏幕: 已断开");
    close(client_socket_control);
    close(server_socket_control);
}


void thread_recv_event(const int &client_socket, const int &frame_delayms)
{
    // 打印opencv版本信息
    print_opencv_version();

    // 首先接收配置数据
    ConfigData config_data;
    if (!recv_config_data(client_socket, config_data))
    {
        logger.log_warn("主控端必须优先发送配置数据以同步相关参数");
        return;
    }
    
    // 获取屏幕信息
    Window root;
    int screen_width,screen_height;
    X11_GetScreenInfo(root, screen_width, screen_height);


    // 控制端想要的屏幕分辨率
    int scaled_width = config_data.scaled_screen_width;
    int scaled_height = config_data.scaled_screen_height;


    logger.log_info("本机屏幕分辨率: %dx%d", screen_width, screen_height);
    logger.log_info("需要缩放分辨率: %dx%d", scaled_width, scaled_height);


    // 创建一个线程，专门用来发送屏幕数据
    // std::thread screen_thread(thread_send_screen, screen_width, screen_height);
    // screen_thread.detach();




    // 创建控制服务套接字
    int sockfd_server_screen = 0;
    logger.log_info("被控端已启动, 监听屏幕端口: %d ...", PORT_SCREEN);
    if (!create_server_socket(sockfd_server_screen, PORT_SCREEN))
    {
        logger.log_error("创建服务端套接字失败");
        return ;
    }
    logger.log_info("被控端已启动, 监听屏幕端口: %d 完成", PORT_SCREEN);


    // 紧接着等待客户端连接
    logger.log_info("等待客户端已连接屏幕: ...");
    // 接受客户端连接
    sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    int sockfd_client_screen = 0;
    sockfd_client_screen = accept(sockfd_server_screen, (struct sockaddr*)&client_addr, &client_len);
    
    if (sockfd_client_screen < 0) {
        logger.log_error("接受连接失败,%s", strerror(errno));
        close(sockfd_server_screen);
        return ;
    }
    
    char client_ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
    logger.log_info("等待客户端已连接屏幕: %s:%d 完成", client_ip, ntohs(client_addr.sin_port));









#if 0
    {
        int width = screen_width;
        int height = screen_height;

        // 1. 捕获并发送屏幕数据
        auto screen_data = capture_screen(root, width, height);
		if (screen_data.size() > 0)
		{
            // 在 server.cpp 的 capture_screen 函数中添加
            std::cout << "捕获屏幕成功，数据大小：" << screen_data.size() << "字节\n";
            save_screen_to_jpg(screen_data, width, height, "screen.jpg");
		}
    }
#endif //if 0




    
    // 主循环：发送屏幕数据并处理输入事件
    bool running = true;
    int loop_count = 0;
    while (running) {


        // 控制帧率，避免CPU占用过高 (5ms=200FPS)
        // usleep(frame_delayus);

        // 控制帧率
        std::this_thread::sleep_for(std::chrono::milliseconds(frame_delayms));
        // std::this_thread::sleep_for(std::chrono::microseconds(1000));


#if 0

		// 服务端替换 capture_screen 调用，发送纯色图像
		auto screen_data = generate_rgb_screen_data(loop_count % 3, SCREEN_WIDTH, SCREEN_HEIGHT);
        
        loop_count += 1;
        if (loop_count == 0xC0000000) {
            // 防止溢出
            loop_count = 0;
        }
        
#endif // RGB image for test


#if 0
        // 1. 捕获并发送屏幕数据
        auto screen_data = capture_screen(display, root, screen_width, screen_height);
        // auto screen_data = capture_screen(display, root, 800, 600);

		if (screen_data.size() > 0)
		{
            // 在 server.cpp 的 capture_screen 函数中添加
            std::cout << "捕获屏幕成功，数据大小：" << screen_data.size() << "字节\n";

            save_screen_to_jpg(screen_data, screen_width, screen_height, "screen.jpg");
		} else
		{
			continue;
		}
#endif //if 0


#if 0
        // 发送屏幕数据
        PacketHeader header;
        header.type = SCREEN_DATA;
        header.data_size = screen_data.size();
        
        if (!send_all(client_socket, &header, sizeof(header)) || 
            !send_all(client_socket, screen_data.data(), screen_data.size())) {
            std::cerr << "发送屏幕数据失败，客户端已断开连接" << std::endl;
            running = false;
            break;
        }
#endif // if 0


#ifdef CONFIG_SEND_FRAME_RAWDATA
    {
        int width = screen_width;
        int height = screen_height;

        // 1. 捕获并发送屏幕数据
        send_frame_rawdata(root, width, height, sockfd_client_screen);
    }
#endif // CONFIG_SEND_FRAME_RAWDATA



        
        // 2. 检查并处理客户端输入事件
        fd_set read_fds;
        FD_ZERO(&read_fds);
        FD_SET(client_socket, &read_fds);
        
        timeval timeout;
        timeout.tv_sec = 0;
        timeout.tv_usec = 10000; // 10ms超时
        
        int activity = select(client_socket + 1, &read_fds, nullptr, nullptr, &timeout);
        if (activity > 0 && FD_ISSET(client_socket, &read_fds)) {
            PacketHeader event_header;
            if (!recv_all(client_socket, &event_header, sizeof(event_header))) {
                logger.log_error("接收事件头部失败，客户端已断开连接");
                running = false;
                break;
            }
            
            // 处理鼠标事件
            if (event_header.type == MOUSE_EVENT && event_header.data_size == sizeof(MouseEvent)) {
                MouseEvent mouse_event;
                if (recv_all(client_socket, &mouse_event, sizeof(mouse_event))) {

                    simulate_mouse_event(mouse_event, 
                        screen_width, screen_height, scaled_width, scaled_height);
                }
            }
            // 处理键盘事件
            else if (event_header.type == KEYBOARD_EVENT && event_header.data_size == sizeof(KeyboardEvent)) {
                KeyboardEvent keyboard_event;
                if (recv_all(client_socket, &keyboard_event, sizeof(keyboard_event))) {
                    simulate_keyboard_event(keyboard_event);
                }
            }
        }
        

    }
}

int main(int argc, const char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "用法: %s  <FPS>\n", argv[0]);
        return 1;
    }

    int fps = std::stoi(argv[1]);
    logger.log_info("设置帧率: %d FPS", fps);

    // 根据帧率计算延时
    int frame_delayms = 1000 / fps;


    // 初始化日志模块
    logger.setConsoleLogLevel(LogLevel::DEBUG);
    logger.setFileLogLevel(LogLevel::INFO);


    // 打印opencv版本信息
    print_opencv_version();
	

    // 初始化X11显示
    if (!X11_init())
    {
        return -1;
    }
    
    // 创建控制服务套接字
    int server_socket_control = 0;
    logger.log_info("被控端已启动, 监听控制端口: %d ...", PORT_CONTROL);
    if (!create_server_socket(server_socket_control, PORT_CONTROL))
    {
        logger.log_error("创建服务端套接字失败");
        return -1;
    }
    logger.log_info("被控端已启动, 监听控制端口: %d 完成", PORT_CONTROL);

    int client_socket_control = 0;
    while (true)
    {

        logger.log_info("等待客户端连接...");

        // 接受客户端连接
        sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        client_socket_control = accept(server_socket_control, (struct sockaddr*)&client_addr, &client_len);
        
        if (client_socket_control < 0) {
            logger.log_error("接受连接失败,%s", strerror(errno));
            close(server_socket_control);
            return 1;
        }
        
        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
        logger.log_info("客户端已连接: %s:%d", client_ip, ntohs(client_addr.sin_port));


        // 创建一个接收线程, 专门用来接收该客户端各种控制事件
        std::thread th_rx_event(thread_recv_event, client_socket_control, frame_delayms);
        th_rx_event.join();

        // 清理客户端资源
        close(client_socket_control);

    }


    if (server_socket_control>0) close(server_socket_control);
    X11_exit();
    return 0;
}

